/**
 *
 * @author DorcasBless
 * you can find the Synaxarium at http://code.google.com/p/synaxarium/
 * April, 2009
 * Version 1.0.0
 *
 * some code snippets were inspired from GoBible http://code.google.com/p/gobible
 *
 */

package com.christian;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;

public class SynMIDlet extends MIDlet {
    public static Display display;

    private boolean midletPaused = false;

    // Display preferences
    public int fontSize = Constatnts.FONT_SIZE_MEDIUM;
    public int fontStyle = Font.STYLE_PLAIN;
    public boolean dateType;
    public boolean fullScreen = false;
    public int theme = Constatnts.THEME_PAPER;
    public boolean reverseColours = false;
    private boolean firstRun = true;

    // midlet canvas and forms
    private SynCanvas canvas;
    private PrefsForm prefsForm;
    private DateSearchForm dateSearchForm;
    private SMSForm smsForm;
    private NameSearchForm nameSearchForm;

    // Alerts
    private Alert alertAbout;
    private static Alert alertWarn;
    private Alert alertMessgeSent;

    //Julian months names in arabic
    public static final String julianMonthsNames[] = {"\u064A\u0646\u0627\u064A\u0631", "\u0641\u0628\u0631\u0627\u064A\u0631", "\u0645\u0627\u0631\u0633", "\u0627\u0628\u0631\u064A\u0644", "\u0645\u0627\u064A\u0648", "\u064A\u0648\u0646\u064A\u0629", "\u064A\u0648\u0644\u064A\u0648", "\u0627\u063A\u0633\u0637\u0633", "\u0633\u0628\u062A\u0645\u0628\u0631", "\u0627\u0643\u062A\u0648\u0628\u0631", "\u0646\u0648\u0641\u0645\u0628\u0631", "\u062F\u064A\u0633\u0645\u0628\u0631"};

    //Calender the will be used for Julian dates
    public static Calendar calendar;

    //<editor-fold defaultstate="collapsed" desc=" Generated Fields ">//GEN-BEGIN:|fields|0|
    //</editor-fold>//GEN-END:|fields|0|
    /**
     * The VisualMIDlet constructor.
     */
    public SynMIDlet() {
    }

    public void showSearchScreen() {
        if (dateSearchForm == null) {
            dateSearchForm = new DateSearchForm(this);
        }
        display.setCurrent(dateSearchForm);
    }

    public void showAboutAlert() {
        display.setCurrent(getAlertAbout());
        canvas.updateGUI();
        
    }

    public void showWarnAlert() {
        display.setCurrent(getAlertWarn());
        canvas.updateGUI();
    }

    public void showAlertMessgeSent(String message) {
        getAlertMessgeSent().setString(message);
        display.setCurrent(getAlertMessgeSent());
        canvas.updateGUI();
    }

    public void showSendSMSScreen(String message) {
        if (smsForm == null) {
            smsForm = new SMSForm(this);
        }
        smsForm.getToTextField().setString(null);
        smsForm.getMessageTextField().setString(message);
        display.setCurrent(smsForm);
    }

    public void showSearchByNameCommand(boolean searchresult) {
        if (nameSearchForm == null) {
            nameSearchForm = new NameSearchForm(this);
        }
        if (searchresult == false) {
            nameSearchForm.getResultChoice().setLabel(null);
            nameSearchForm.getResultChoice().deleteAll();
        }
        display.setCurrent(nameSearchForm);
    }

    //<editor-fold defaultstate="collapsed" desc=" Generated Methods ">//GEN-BEGIN:|methods|0|
    //</editor-fold>//GEN-END:|methods|0|

    //<editor-fold defaultstate="collapsed" desc=" Generated Method: initialize ">//GEN-BEGIN:|0-initialize|0|0-preInitialize
    /**
     * Initilizes the application.
     * It is called only once when the MIDlet is started. The method is called before the <code>startMIDlet</code> method.
     */
    private void initialize() {//GEN-END:|0-initialize|0|0-preInitialize
        // write pre-initialize user code here
//GEN-LINE:|0-initialize|1|0-postInitialize
        // write post-initialize user code here
    }//GEN-BEGIN:|0-initialize|2|
    //</editor-fold>//GEN-END:|0-initialize|2|

    //<editor-fold defaultstate="collapsed" desc=" Generated Method: startMIDlet ">//GEN-BEGIN:|3-startMIDlet|0|3-preAction
    /**
     * Performs an action assigned to the Mobile Device - MIDlet Started point.
     */
    public void startMIDlet() {//GEN-END:|3-startMIDlet|0|3-preAction
        // write pre-action user code here
        if (firstRun) {
            firstRun = false;
            display = Display.getDisplay(this);
            readPreferences();
            canvas = new SynCanvas(this);
            calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            String dateStr = getCorrectDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH));
            if (canvas.init(dateStr))
            {
                setCanvasTitle();
                showMainScreen();
            }
            else
            {
                display.setCurrent(canvas);
            }
        }

//GEN-LINE:|3-startMIDlet|1|3-postAction
    // write post-action user code here
    }//GEN-BEGIN:|3-startMIDlet|2|
    //</editor-fold>//GEN-END:|3-startMIDlet|2|

    //<editor-fold defaultstate="collapsed" desc=" Generated Method: resumeMIDlet ">//GEN-BEGIN:|4-resumeMIDlet|0|4-preAction
    /**
     * Performs an action assigned to the Mobile Device - MIDlet Resumed point.
     */
    public void resumeMIDlet() {//GEN-END:|4-resumeMIDlet|0|4-preAction
        // write pre-action user code here
//GEN-LINE:|4-resumeMIDlet|1|4-postAction
        // write post-action user code here
    }//GEN-BEGIN:|4-resumeMIDlet|2|
    //</editor-fold>//GEN-END:|4-resumeMIDlet|2|

    //<editor-fold defaultstate="collapsed" desc=" Generated Method: switchDisplayable ">//GEN-BEGIN:|5-switchDisplayable|0|5-preSwitch
    /**
     * Switches a current displayable in a display. The <code>display</code> instance is taken from <code>getDisplay</code> method. This method is used by all actions in the design for switching displayable.
     * @param alert the Alert which is temporarily set to the display; if <code>null</code>, then <code>nextDisplayable</code> is set immediately
     * @param nextDisplayable the Displayable to be set
     */
    public void switchDisplayable(Alert alert, Displayable nextDisplayable) {//GEN-END:|5-switchDisplayable|0|5-preSwitch
        // write pre-switch user code here
        Display display = getDisplay();//GEN-BEGIN:|5-switchDisplayable|1|5-postSwitch
        if (alert == null) {
            display.setCurrent(nextDisplayable);
        } else {
            display.setCurrent(alert, nextDisplayable);
        }//GEN-END:|5-switchDisplayable|1|5-postSwitch
    // write post-switch user code here
    }//GEN-BEGIN:|5-switchDisplayable|2|
    //</editor-fold>//GEN-END:|5-switchDisplayable|2|

    /**
     * Returns a display instance.
     * @return the display instance.
     */
    public Display getDisplay() {
        return Display.getDisplay(this);
    }

    /**
     * Exits MIDlet.
     */
    public void exitMIDlet() {
        // Save the preferences
        writePreferences();
        switchDisplayable(null, null);
        destroyApp(true);
        notifyDestroyed();
    }

    /**
     * Called when MIDlet is started.
     * Checks whether the MIDlet have been already started and initialize/starts or resumes the MIDlet.
     */
    public void startApp() {
        if (midletPaused) {
            resumeMIDlet();
        } else {
            initialize();
            startMIDlet();
        }
        midletPaused = false;
    }

    /**
     * Called when MIDlet is paused.
     */
    public void pauseApp() {
        midletPaused = true;
    }

    /**
     * Called to signal the MIDlet to terminate.
     * @param unconditional if true, then the MIDlet has to be unconditionally terminated and all resources has to be released.
     */
    public void destroyApp(boolean unconditional) {
    }

    /**
     * This method is called to redisplay the main screen
     */
    private void showMainScreen() {
        // Set up the theme colours
        int textColour = Constatnts.THEME_TEXT_COLOUR[theme];
        int backColour = Constatnts.THEME_BACK_COLOUR[theme];

        if (reverseColours) {
            int temp = textColour;
            textColour = backColour;
            backColour = temp;
            canvas.highlightColour = backColour;
        } else {
            canvas.highlightColour = Constatnts.THEME_HIGHLIGHT_COLOUR[theme];
        }

        canvas.textColour = textColour;
        canvas.backColour = backColour;

        setCanvasTitle();
        
        if (Constatnts.MIDP20) {
            canvas.setFullScreenMode(fullScreen);
        }       
        display.setCurrent(canvas);
        
    }

    public void showNewMainScreen()
    {
        showMainScreen();
        canvas.fullUpdate();
    }

    public void showSameMainScreen()
    {
        showMainScreen();
        canvas.updateGUI();
    }

    public void showPrefsScreen() {
        if (prefsForm == null) {
            prefsForm = new PrefsForm(this);
        }
        display.setCurrent(prefsForm);
    }

    /**
     * The application's state is stored in the record store under the name "SynPreferences".
     */
    private void readPreferences() {
        try {
            // Open the "SynPreferences" record store and create it if necessary
            RecordStore store = RecordStore.openRecordStore("SynPreferences", true);

            // Make sure the record store isn't empty
            if (store.getNumRecords() > 0) {
                byte[] data = store.getRecord(1);

                DataInputStream input = new DataInputStream(new ByteArrayInputStream(data));

                // Get the font size
                fontSize = input.readByte();

                // Read in full screen mode
                fullScreen = input.readBoolean();

                // Read in theme
                theme = input.readByte();

                // Read in reverse colours
                reverseColours = input.readBoolean();

                // Get the font style
                fontStyle = input.readByte();

                // Get the date type
                dateType = input.readBoolean();

                input.close();
            }
        } catch (IOException ee) {
            getAlertWarn().setString(ee.getMessage());
            showWarnAlert();
        } catch (RecordStoreException e) {
            getAlertWarn().setString(e.getMessage());
            showWarnAlert();
        }
    }

    /**
     * Save the application's state so that it can return to the same state when reopened.
     */
    public void writePreferences() {
        try {
            // Open the "SynPreferences" record store and create it if necessary
            RecordStore store = RecordStore.openRecordStore("SynPreferences", true);

            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            DataOutputStream output = new DataOutputStream(byteArrayOutputStream);

            // Set the font size
            output.write(fontSize);

            // Write out full screen mode
            output.writeBoolean(fullScreen);

            // Write out theme
            output.write(theme);

            // Write out reverse colours
            output.writeBoolean(reverseColours);

            // Write out the font style
            output.write(fontStyle);

            // Write out the DateType 0=julian, 1= coptic
            output.writeBoolean(dateType);

            output.close();

            byte[] data = byteArrayOutputStream.toByteArray();

            // Make sure the record store isn't empty
            if (store.getNumRecords() > 0) {
                store.setRecord(1, data, 0, data.length);
            } else {
                // Create record if it doesn't exist
                store.addRecord(data, 0, data.length);
            }
            store.closeRecordStore();
        } catch (IOException e) {
            getAlertWarn().setString(e.getMessage());
            showWarnAlert();
        } catch (RecordStoreException e) {
            getAlertWarn().setString(e.getMessage());
            showWarnAlert();
        }
    }

    /**
     * @return the canvas
     */
    public SynCanvas getCanvas() {
        return canvas;
    }

    public static String getCorrectDate(int year, int month, int day) {
        // The year before the leap year
        if (year == 2007 || year == 2011 || year == 2015) {
            // 1 jan to 10 sept -> fine

            // 11 sept -> day=extra.text
            if (month == 9 && day == 11) {
                return "/9/extra.txt";
            } else if (month == 9 && day >= 12 && day <= 30) {
                day--;
                return "/9/" + day + ".txt";
            } else if (month == 10 || month == 12) {
                day--;
                if (day == 0) {
                    month--;
                    day = 30;
                }
                return "/" + month + "/" + day + ".txt";
            } else if (month == 11) {
                day--;
                if (day == 0) {
                    month = 10;
                    day = 31;
                }
                return "/" + month + "/" + day + ".txt";
            }
        }
        //leap year case
        else if (year == 2008 || year == 2012 || year == 2016) {
            if (month == 1) {
                day--;
                if (day == 0) {
                    month = 12;
                    day = 31;
                }
                return "/" + month + "/" + day + ".txt";
            } else if (month == 2) {
                day--;
                if (day == 0) {
                    month = 1;
                    day = 31;
                }
                return "/" + month + "/" + day + ".txt";
            }
        }

        //refernce years 2009, 2010, 2013, 2014
        return "/" + month + "/" + day + ".txt";

    }

    public void setCanvasTitle() {
//        if (dateType) {
//            canvas.setTitle(canvas.getCopticDate());
//        } else {
//            canvas.setTitle(calendar.get(Calendar.DAY_OF_MONTH) + " " + julianMonthsNames[calendar.get(Calendar.MONTH)]);
//        }
        canvas.setTitle(calendar.get(Calendar.DAY_OF_MONTH) + " " + julianMonthsNames[calendar.get(Calendar.MONTH)]+" - "+canvas.getCopticDate());
    }

    /**
     * @return the alertAbout
     */
    public Alert getAlertAbout() {
        if (alertAbout == null) {
            alertAbout = new Alert("\u0627\u0644\u0633\u0646\u0643\u0633\u0627\u0631", "By DorcasBless http://code.google.com/p/synaxarium/, \"I can do all things through Christ which strengtheneth me\", Version 1.0.0, April 2009.", null, AlertType.INFO);
            alertAbout.setTimeout(Alert.FOREVER);
        }
        return alertAbout;
    }

    /**
     * @return the alertWarn
     */
    public Alert getAlertWarn() {
        if (alertWarn == null) {
            alertWarn = new Alert("\u062A\u062D\u0630\u064A\u0631", null, null, AlertType.WARNING);
            alertWarn.setTimeout(Alert.FOREVER);
        }
        return alertWarn;
    }

    /**
     * @return the alertMessgeSent
     */
    public Alert getAlertMessgeSent() {
        if (alertMessgeSent == null) {
            alertMessgeSent = new Alert(null, "\u062A\u0645 \u0627\u0631\u0633\u0627\u0644 \u0627\u0644\u0631\u0633\u0627\u0644\u0629 \u0628\u0646\u062C\u0627\u062D", null, AlertType.INFO);
            alertMessgeSent.setTimeout(Alert.FOREVER);
        }
        return alertMessgeSent;
    }

    public SynMIDlet getMidlet()
    {
        return this;
    }
}
